//
// Created by Administrator on 2015/5/22.
//
#pragma once

#if __cplusplus < 201103L && !defined(_MSC_VER)
#error "should use c++11 to compile this framework!"
#endif
#if defined(_MSC_VER)
#pragma comment(lib, "wsock32.lib")
#endif

#include <vector>
#include <set>
#include <string>
#include <map>
#include <unordered_map>
#include <cassert>
#include <memory>

#if (defined(__WIN32__) && !defined(__CYGWIN__)) || defined(_MSC_VER)
#define __ESVR_WIN32__
typedef unsigned int socket_t;
typedef int socklen_t;
const socket_t  socket_t_invalid = 1;
const socket_t  sock_t_invalid = 1;
#define ERRNO       (WSAGetLastError())
#define NEEDBLOCK   WSAEWOULDBLOCK
#include <winsock.h>
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__unix__) || defined(__CYGWIN32__) || defined(__APPLE__)
#define __ESVR_LINUX__
typedef  int socket_t;
#include <sys/socket.h>
#include <errno.h>
const socket_t  socket_t_invalid = -1;
const socket_t  sock_t_invalid = -1;
#define ERRNO (errno)
#define NEEDBLOCK   EAGAIN
#endif

#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__MINGW32__)
#define CHECK_RESULT __attribute__ ((unused))
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
#define CHECK_RESULT _Check_return_
#define noexcept
#else
#define CHECK_RESULT
#define noexcept
#endif

#define HAVE_SELECT     #select 肯定有的
#if defined(__linux__)
#include <linux/version.h>
#define HAVE_POLL  //老的linux内核用poll
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
#define HAVE_EPOLL //新的linux内核用epoll
#endif
#endif

#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__APPLE__)
#define HAVE_POLL //cygwin&mac os支持poll
#endif

#define DEF_EMPTY_EVENT(NAME, TYPE) class NAME : public Event {\
private:\
public:\
	NAME(){}\
	NAME(const NAME& t){}\
	std::string to_string() const {return #NAME;}\
	static ES_EVENT type(){return TYPE;}\
	static std::string type_str(){return get_event_str(TYPE);}\
}

#define DEF_FD_EVENT(NAME, TYPE) class NAME : public Event {\
private:\
	socket_t m_fd = socket_t_invalid;\
public:\
	NAME(){} \
	NAME(socket_t fd) : m_fd(fd){}\
	NAME(const NAME& t) {m_fd = t.m_fd;}\
	socket_t fd() const {return m_fd;}\
	std::string to_string() const {return #NAME;}\
	static ES_EVENT type(){return TYPE;}\
	static std::string type_str(){return get_event_str(TYPE);}\
}

#define DEF_FD_BUFFER_EVENT(NAME, TYPE) class NAME : public Event {\
private:\
	socket_t m_fd = sock_t_invalid;\
	const char* m_data = NULL;\
	size_t m_len = 0;\
public:\
	NAME(){}\
	NAME(socket_t fd, const char* data, size_t len) : m_fd(fd), m_data(data), m_len(len){}\
	NAME(const NAME& t){m_fd = t.m_fd; m_data = t.m_data; m_len = t.m_len;}\
	socket_t fd() const {return m_fd;}\
	std::string to_string() const {return #NAME;}\
	size_t len() const {return m_len;}\
	const char* data() const { return m_data;}\
	static ES_EVENT type(){return TYPE;}\
	static std::string type_str(){return get_event_str(TYPE);}\
};

namespace esvr
{
typedef enum
{
	ES_DEFAULT      = 0x0000, //no event
	ES_READ         = 0x0001, //read event
	ES_WRITE        = 0x0002, //write event
	ES_CONNECTED    = 0x0004, //connect event
	ES_CLOSED       = 0x0008, //closed event
	ES_IDLE         = 0x0010, //server idle event
	ES_MODIFIED     = 0x0020, //file modify event
} ES_EVENT;

extern std::string get_event_str(ES_EVENT event);

template <typename T>
class Creator
{
public:
	static T* create()
	{
		return new T;
	}

	static void destroy(T* &v)
	{
		delete v;
		v = NULL;
	}
};

template <typename T>
class AutoReleaseSingleton
{
private:
	T* m_handler;

private:
	AutoReleaseSingleton(const AutoReleaseSingleton&): m_handler(NULL){}
	AutoReleaseSingleton& operator = (const AutoReleaseSingleton&){return *this;}

public:
	AutoReleaseSingleton(T* handler=NULL) : m_handler(handler) {}
	void AllocInst()
	{
		if(!m_handler) m_handler = T::create();
	}

	~AutoReleaseSingleton()
	{
		if(m_handler) T::destroy(m_handler);
		m_handler = NULL;
	}

	T* data() noexcept
			{
		AllocInst();
		return m_handler;
			}

	T* operator& () noexcept
			{
		AllocInst();
		return m_handler;
			}

	T& operator* () noexcept
			{
		AllocInst();
		return *m_handler;
			}
};

template<typename T>
class LockFreeQueue;

class BlockList;

class IOManager
{
public:
	static IOManager& instance()
	{
		static IOManager manager;
		return manager;
	}

	static IOManager& get_instance()
	{
		return instance();
	}

public:
	void start(socket_t server_fd, int millisecond=100)
	{
		m_serverfd = server_fd;
    m_wait_millisecond = millisecond;
		m_start = true;
    m_active_clients.clear();
		before_start();
		main_loop();
	}

	int send(socket_t /*cli_fd*/, const char* /*buffer*/, const size_t /*size*/);

	void stop();

	virtual void before_start();

	virtual void before_stop();

	virtual void after_stop();

	virtual void before_loop_once();

	virtual void after_loop_once();

  virtual void on_idle();

	//thread safe.
	void force_close(socket_t fd);

protected:

	void main_loop();

	void readable_buffer(socket_t fd, char* & buffer, size_t& readable_len);

	void writable_buffer(socket_t fd, char* & buffer, size_t& writable_len);

	void increase_readable(socket_t fd, size_t len);

	void decrease_readable(socket_t fd, size_t len);

	void new_fd(socket_t fd);

	void delete_fd(socket_t fd);

	LockFreeQueue<socket_t> * get_to_close_queue();

private:
	volatile bool m_start = false;
	socket_t m_serverfd = socket_t_invalid;
	int m_wait_millisecond = 0;
  std::string m_io_type = "None";
	std::unordered_map<socket_t, BlockList*> m_active_clients;

};

class Event
{

public:
	Event() = default;
	ES_EVENT type(){return ES_DEFAULT;}
	Event(const Event&) = delete;

};

DEF_FD_EVENT(ConnectedEvent, ES_CONNECTED);
DEF_FD_EVENT(ClosedEvent, ES_CLOSED);
DEF_FD_BUFFER_EVENT(ReadEvent, ES_READ);
DEF_FD_BUFFER_EVENT(WriteEvent, ES_WRITE);
DEF_EMPTY_EVENT(IdleEvent, ES_IDLE);

template<typename T>
class EventListener
{
private:
	int m_listen_flag{0};

public:
	virtual void on_event(const T*){}
	virtual ~EventListener(){}
	EventListener(){m_listen_flag |= (int) T::type();}
};

class EventBus
{

public:

	typedef std::map<ES_EVENT, std::set<void*>> listener_map_t;

	static EventBus& get_instance()
	{
		static EventBus event_bus;
		return event_bus;
	}

	static EventBus& instance()
	{
		return get_instance();
	}

	template<typename T>
	void add_handler(EventListener<T>* listener)
	{
		auto it = m_listeners.find(T::type());
		if(it == m_listeners.end())
		{
			m_listeners[T::type()] = std::set<void*>();
			it = m_listeners.find(T::type());
		}
		it->second.insert(listener);
	}

	template<typename T>
	void remove_handler(EventListener<T>* listener)
	{
		auto it = m_listeners.find(T::type());
		if(it != m_listeners.end())
		{
			it->second.erase(listener);
		}
	}

	template<typename T>
	void fire_event(const T* event);

protected:
	template<typename T>
	void dispatch_event(const T* event, bool free=false);

private:
	listener_map_t m_listeners;
};

};
